package com.knife.oauth.security.config;

import com.knife.oauth.security.customer.cache.v2.KnifeIpCache;
import com.knife.oauth.security.customer.chain.KnifeHelperChain;
import com.knife.oauth.security.customer.filter.KnifeBlackListFilter;
import com.knife.oauth.security.customer.filter.KnifeGatewayHelperFilter;
import com.knife.oauth.security.customer.filter.KnifeHelperFilter;
import com.knife.redis.KnifeRedisHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * security配置
 *
 * @author： 76875
 * @date： 2022/4/13 星期三 15:26
 * @description：
 * @modifiedBy：
 * @version: 1.0
 */
@Configuration
@EnableConfigurationProperties({GatewayProperties.class})
@SuppressWarnings("ALL")
public class KnifeGatewayConfigure {

    @Autowired
    private KnifeRedisHelper knifeRedisHelper;

    @Autowired
    private KnifeIpCache knifeIpCache;

    @Bean
    public KnifeBlackListFilter knifeBlackListFilter() {
        KnifeBlackListFilter knifeBlackListFilter = new KnifeBlackListFilter(knifeRedisHelper, knifeIpCache);
        return knifeBlackListFilter;
    }


    // 这里的参数会自动封装,会扫描spring 容器中是HelperFilter类型的 bean,组合成 list 作为参数
    // 前提是必须在Spring 的自动装配类配置中
    @Bean
    public KnifeHelperChain knifeHelperChain(Optional<List<KnifeHelperFilter>> optionalHelperFilters) {
        return new KnifeHelperChain(optionalHelperFilters);
    }


    @Bean
    public KnifeGatewayHelperFilter knifeGatewayHelperFilter(@Qualifier(value = "knifeHelperChain") KnifeHelperChain knifeHelperChain) {
        KnifeGatewayHelperFilter knifeGatewayHelperFilter = new KnifeGatewayHelperFilter(knifeHelperChain);
        return knifeGatewayHelperFilter;
    }


    /**
     * 解决跨域问题
     *
     * @return 跨域声明
     */
    @Bean
    @Order(Integer.MIN_VALUE)
    public CorsWebFilter corsWebFilter(GatewayProperties properties) {
        org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource source = new org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // 允许向该服务器提交请求的URI，*表示全部允许。。这里尽量限制来源域，比如http://xxxx:8080 ,以降低安全风险。
        for (String allowedOrigin : properties.getCors().getAllowedOrigins()) {
            config.addAllowedOrigin(allowedOrigin);
        }
        // 允许访问的头信息,*表示全部
        for (String allowedHeader : properties.getCors().getAllowedHeaders()) {
            config.addAllowedHeader(allowedHeader);
        }
        // 允许提交请求的方法，*表示全部允许，也可以单独设置GET、PUT等
        for (String allowedMethod : properties.getCors().getAllowedMethods()) {
            config.addAllowedMethod(allowedMethod);
        }
        // 预检请求的缓存时间（秒），即在这个时间段里，对于相同的跨域请求不会再预检了
        config.setMaxAge(18000L);
        //添加response暴露的header
        String[] responseHeader =
                {"date", "content-encoding", "server", "etag", "vary", "Cache-Control", "Last-Modified",
                        "content-type", "transfer-encoding", "connection", "x-application-context"};
        config.setExposedHeaders(Arrays.asList(responseHeader));
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}
